package ru.susu.algebra.util;

import java.math.BigInteger;

import ru.susu.algebra.wrapper.number.INumberWrapper;

/**
 * @author akargapolov
 * @since: 14.10.2010
 */
public class NumberWrapperUtilities
{

	public static <T> INumberWrapper<T> pow(INumberWrapper<T> one, INumberWrapper<T> wrapper, BigInteger pow) throws Exception
	{
		INumberWrapper<T> result = one;
		INumberWrapper<T> tmp = wrapper;
		BigInteger two = BigInteger.valueOf(2);
		while (!pow.equals(BigInteger.ZERO))
		{
			if (pow.mod(two).intValue() == 1)
			{
				result = result.multiply(tmp);
			}
			pow = pow.divide(two);
			tmp = tmp.multiply(tmp);
		}
		return result;
	}

	public static <T> INumberWrapper<T> modPow(INumberWrapper<T> one, INumberWrapper<T> wrapper, BigInteger pow, BigInteger mod)
	{
		try
		{
			INumberWrapper<T> result = one;
			INumberWrapper<T> tmp = wrapper;
			BigInteger two = BigInteger.valueOf(2);
			while (!pow.equals(BigInteger.ZERO))
			{
				if (pow.mod(two).intValue() == 1)
				{
					result = result.multiply(tmp).mod(mod);
				}
				pow = pow.divide(two);
				tmp = tmp.multiply(tmp).mod(mod);
			}
			return result;
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}
}
